<template>
  <el-config-provider :locale="zhCn">
    <div class="page" v-loading="initialLoading" element-loading-text="正在加载数据...">
      <div class="header">
        <div class="info">
          <div class="row"><span class="label">模板版本代码：</span><span>{{ tpl?.template_version_code }}</span></div>
          <div class="row"><span class="label">名称：</span><span>{{ tpl?.name }}</span></div>
          <div class="row"><span class="label">指标版本ID：</span><span>{{ tpl?.indicator_version_id || '-' }}</span></div>
          <div class="row"><span class="label">Word模板MongoID：</span><span>{{ tpl?.word_template_mongo_id || '-' }}</span></div>
        </div>
        <div class="actions">
          <el-button @click="back">返回</el-button>
          <el-button @click="toggleAll">{{ expandLabel }}</el-button>
        </div>
      </div>
      <div class="content">
          <div class="sidebar">
          <div class="sidebar-tools">
            <el-button type="primary" @click="openCreate">新建</el-button>
          </div>
          <el-tree :data="treeData" :props="treeProps" node-key="key" :default-expanded-keys="expandedKeys" :key="treeRefreshKey" @node-expand="onTreeExpand" @node-collapse="onTreeCollapse">
            <template #default="{ node, data }">
              <div class="tree-row">
                <el-tooltip :content="`${data.data.section_no} ${data.data.section_name}`" placement="top" effect="dark">
                  <span class="node-label" @click.stop="scrollToSection(data.data.section_no)">{{ data.data.section_no }} {{ data.data.section_name }}</span>
                </el-tooltip>
                <el-dropdown class="menu-wrap" trigger="click" @command="(cmd:string) => onNodeCommand(cmd, data.data)">
                  <span class="more" @click.stop @mousedown.stop><el-icon><MoreFilled /></el-icon></span>
                  <template #dropdown>
                    <el-dropdown-menu>
                    <el-dropdown-item v-if="data.data.level === 1" command="cloneTop">克隆</el-dropdown-item>
                    <el-dropdown-item v-if="data.data.level === 2" command="cloneSub">克隆</el-dropdown-item>
                      <el-dropdown-item command="addChild">添加子级</el-dropdown-item>
                      <el-dropdown-item command="edit">编辑</el-dropdown-item>
                      <el-dropdown-item command="delete">删除</el-dropdown-item>
                    </el-dropdown-menu>
                  </template>
                </el-dropdown>
              </div>
            </template>
          </el-tree>
        </div>
        <div class="detail" ref="detailEl">
          <div class="preview">
            <div v-for="s in outlineSorted" :key="s.section_no" :id="'section-' + s.section_no" :class="['section', 'l' + (s.level || 1)]">
              <div class="title-row" @click="toggleSection(s)">
                <span class="caret">{{ isCollapsed(s) ? '▶' : '▼' }}</span>
                <div :class="titleClass(s.level)">{{ s.section_no }} {{ s.section_name }}</div>
              </div>
              <div v-show="!isCollapsed(s)">
                <el-input type="textarea" :rows="s.level===1?4:s.level===2?3:2" placeholder="（此处为占位正文，用于预览）" />
              </div>
            </div>
          </div>
        </div>
      </div>
      <el-dialog v-model="showDialog" :title="dialogTitle" width="560px" destroy-on-close>
        <el-form :model="form" label-width="120px">
          <el-form-item label="章节编号">
            <el-input v-model="form.section_no" placeholder="如 1 或 1.1 或 2.3.1" />
          </el-form-item>
          <el-form-item label="章节名称">
            <el-input v-model="form.section_name" placeholder="章节标题" />
          </el-form-item>
          <el-form-item label="层级">
            <el-select v-model="form.level" style="width:180px">
              <el-option v-for="lv in [1,2,3]" :key="lv" :label="lv" :value="lv" />
            </el-select>
          </el-form-item>
          <el-form-item label="样式">
            <el-select v-model="form.style" style="width:220px">
              <el-option v-for="st in styleOptions" :key="st" :label="st" :value="st" />
            </el-select>
          </el-form-item>
          <el-form-item label="必填">
            <el-switch v-model="form.required" />
          </el-form-item>
        </el-form>
        <template #footer>
          <el-button @click="showDialog=false">取消</el-button>
          <el-button type="primary" @click="submit">保存</el-button>
        </template>
      </el-dialog>
    </div>
  </el-config-provider>
</template>

<script setup lang="ts">
import { ref, reactive, computed, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import zhCn from 'element-plus/es/locale/lang/zh-cn'
import { api } from '../../api/client'
import { ElMessage, ElMessageBox } from 'element-plus'
import { MoreFilled } from '@element-plus/icons-vue'

const route = useRoute()
const router = useRouter()

const tpl = ref<any>(null)
const outline = ref<any[]>([])
const activeKey = ref('0')
const current = ref<any>(null)
const selectedKey = ref<string | null>(null)
let editingFromNode: any = null
const initialLoading = ref(true)

function onNodeCommand(cmd: string, data: any) {
  if (cmd === 'edit') {
    openEdit(data)
  } else if (cmd === 'delete') {
    removeNode(data)
  } else if (cmd === 'addChild') {
    openAddChild(data)
  } else if (cmd === 'cloneTop') {
    openCloneTop(data)
  } else if (cmd === 'cloneSub') {
    openCloneSub(data)
  }
}

function back() { router.push('/admin/evaluation-templates') }

async function load() {
  const id = String(route.params.id || '')
  if (!id) return
  const t = await api.get(`/evaluation-templates/${id}`)
  tpl.value = t.data
  if (tpl.value?.template_version_code) {
    const o = await api.get(`/template-outline/${tpl.value.template_version_code}`)
    outline.value = o.data?.outline || []
    if (outline.value.length) { selectedKey.value = makeKey(outline.value[0]); }
  }
}

onMounted(async () => {
  initialLoading.value = true
  try {
    await load()
    initTreeExpanded()
  } finally {
    initialLoading.value = false
  }
})

// 目录树构建
const treeProps = { label: 'label', children: 'children' }
const treeData = computed(() => buildTree(outline.value))
const expandedAll = ref(true)
const treeRefreshKey = ref(0)
const treeExpandedSet = ref<Set<string>>(new Set())
const expandedKeys = computed(() => Array.from(treeExpandedSet.value))
function buildTree(items: any[]) {
  const root: any[] = []
  const byKey: Record<string, any> = {}
  function parentKey(no: string) {
    const parts = String(no || '').split('.')
    if (parts.length <= 1) return ''
    return parts.slice(0, -1).join('.')
  }
  for (const s of items || []) {
    const key = makeKey(s)
    const node = { key, label: `${s.section_no} ${s.section_name}`, data: s, children: [] as any[] }
    byKey[key] = node
  }
  for (const s of items || []) {
    const key = makeKey(s)
    const pkey = parentKey(s.section_no)
    const pnode = pkey ? byKey[pkey] : null
    const node = byKey[key]
    if (pnode) pnode.children.push(node)
    else root.push(node)
  }
  return root
}
function makeKey(s: any) { return String(s.section_no) }
const outlineSorted = computed(() => [...(outline.value || [])].sort((a, b) => a.section_no.localeCompare(b.section_no)))
// 预览折叠
const collapsedSet = ref<Set<string>>(new Set())
function isCollapsed(s: any) { return collapsedSet.value.has(String(s.section_no)) }
function toggleSection(s: any) {
  const k = String(s.section_no)
  if (collapsedSet.value.has(k)) collapsedSet.value.delete(k)
  else collapsedSet.value.add(k)
  collapsedSet.value = new Set(Array.from(collapsedSet.value))
}

const detailEl = ref<HTMLDivElement | null>(null)
function scrollToSection(no: string) {
  const container = detailEl.value
  const el = document.getElementById(`section-${no}`)
  if (!container || !el) return
  const k = String(no)
  if (collapsedSet.value.has(k)) {
    const next = new Set(collapsedSet.value)
    next.delete(k)
    collapsedSet.value = next
  }
  const cRect = container.getBoundingClientRect()
  const eRect = el.getBoundingClientRect()
  const top = container.scrollTop + (eRect.top - cRect.top) - 8
  container.scrollTo({ top, behavior: 'smooth' })
}
const expandLabel = computed(() => expandedAll.value ? '收起目录与预览' : '展开目录与预览')
function toggleAll() {
  expandedAll.value = !expandedAll.value
  if (expandedAll.value) {
    treeExpandedSet.value = new Set((outline.value || []).map((s:any) => String(s.section_no)))
    collapsedSet.value = new Set()
  } else {
    treeExpandedSet.value = new Set()
    collapsedSet.value = new Set((outline.value || []).map((s:any) => String(s.section_no)))
  }
  treeRefreshKey.value++
}

function onTreeExpand(data: any, node: any) {
  const k = String((node && node.key) || (data && (data.key || data.section_no)))
  if (!treeExpandedSet.value.has(k)) {
    const next = new Set(treeExpandedSet.value)
    next.add(k)
    treeExpandedSet.value = next
  }
}
function onTreeCollapse(data: any, node: any) {
  const k = String((node && node.key) || (data && (data.key || data.section_no)))
  if (treeExpandedSet.value.has(k)) {
    const next = new Set(treeExpandedSet.value)
    next.delete(k)
    treeExpandedSet.value = next
  }
}

function initTreeExpanded() {
  if (treeExpandedSet.value.size === 0) {
    if (expandedAll.value) {
      treeExpandedSet.value = new Set((outline.value || []).map((s:any) => String(s.section_no)))
    } else {
      treeExpandedSet.value = new Set()
    }
    treeRefreshKey.value++
  }
}

// 标题样式映射
function titleClass(level: number) {
  if (level === 1) return 'h1'
  if (level === 2) return 'h2'
  return 'h3'
}

// 新建/编辑/删除
const form = reactive({ section_no: '', section_name: '', level: 1, style: 'Heading 1', required: true })
const styleOptions = ['Heading 1','Heading 2','Heading 3','Title','Subtitle','Normal']
const showDialog = ref(false)
const dialogTitle = ref('')
const cloneMode = ref(false)
function openCreate() {
  dialogTitle.value = '新建章节'
  Object.assign(form, { section_no: '', section_name: '', level: 1, style: 'Heading 1', required: true })
  showDialog.value = true
  cloneMode.value = false
}
function openEdit(s: any) {
  editingFromNode = s
  dialogTitle.value = '编辑章节'
  Object.assign(form, { section_no: s.section_no, section_name: s.section_name, level: s.level, style: s.style || 'Heading 1', required: !!s.required })
  showDialog.value = true
}
function openAddChild(parent: any) {
  const children = (outline.value || []).filter((x) => {
    const parts = String(x.section_no || '').split('.')
    return parts.slice(0, -1).join('.') === parent.section_no
  })
  const next = (() => {
    const nums = children.map((c) => {
      const parts = String(c.section_no || '').split('.')
      const last = parts[parts.length - 1]
      const n = parseInt(last, 10)
      return isNaN(n) ? 0 : n
    })
    const max = nums.length ? Math.max(...nums) : 0
    return String(max + 1)
  })()
  const lv = Math.min((parent.level || 1) + 1, 3)
  const style = lv === 1 ? 'Heading 1' : lv === 2 ? 'Heading 2' : 'Heading 3'
  dialogTitle.value = '新建章节'
  Object.assign(form, { section_no: `${parent.section_no}.${next}`, section_name: '', level: lv, style, required: true })
  showDialog.value = true
}

function openCloneTop(s: any) {
  const topLevels = (outline.value || []).filter((x) => String(x.section_no || '').indexOf('.') === -1)
  const nums = topLevels.map((t) => {
    const n = parseInt(String(t.section_no || ''), 10)
    return isNaN(n) ? 0 : n
  })
  const next = (nums.length ? Math.max(...nums) + 1 : 1).toString()
  dialogTitle.value = '克隆顶级章节'
  Object.assign(form, {
    section_no: next,
    section_name: s.section_name,
    level: 1,
    style: s.style || 'Heading 1',
    required: s.required ?? true
  })
  showDialog.value = true
  editingFromNode = s
  cloneMode.value = true
}
function openCloneSub(s: any) {
  const parentNo = (() => {
    const parts = String(s.section_no || '').split('.')
    return parts.slice(0, -1).join('.')
  })()
  const children = (outline.value || []).filter((x) => {
    const parts = String(x.section_no || '').split('.')
    return parts.slice(0, -1).join('.') === parentNo
  })
  const next = (() => {
    const nums = children.map((c) => {
      const parts = String(c.section_no || '').split('.')
      const last = parts[parts.length - 1]
      const n = parseInt(last, 10)
      return isNaN(n) ? 0 : n
    })
    const max = nums.length ? Math.max(...nums) : 0
    return String(max + 1)
  })()
  dialogTitle.value = '克隆二级章节'
  Object.assign(form, {
    section_no: `${parentNo}.${next}`,
    section_name: s.section_name,
    level: 2,
    style: s.style || 'Heading 2',
    required: s.required ?? true
  })
  showDialog.value = true
  editingFromNode = s
  cloneMode.value = true
}
async function removeNode(s: any) {
  if (!tpl.value) return
  await ElMessageBox.confirm('确定删除该章节？', '提示', { type: 'warning' })
  try {
    await api.delete(`/template-outline/${tpl.value.template_version_code}/sections/${s.section_no}`)
    await reloadOutline()
    ElMessage.success('已删除')
  } catch (e: any) {
    ElMessage.error(e?.response?.data?.detail || '删除失败')
  }
}

async function reloadOutline() {
  const o = await api.get(`/template-outline/${tpl.value.template_version_code}`)
  outline.value = o.data?.outline || []
  treeRefreshKey.value++
}

async function submit() {
  if (!tpl.value) return
  // 样式联动提示：仅在编辑且样式变化时提示
  const s = editingFromNode || outline.value.find((x) => makeKey(x) === selectedKey.value)
  const willUpdateStyle = s && s.level === form.level && s.style !== form.style
  try {
    if ((dialogTitle.value || '').includes('新建') && !cloneMode.value) {
      await api.post(`/template-outline/${tpl.value.template_version_code}/sections`, form)
    } else if (cloneMode.value && editingFromNode) {
      const srcTop = String(editingFromNode.section_no)
      const destTop = String(form.section_no)
      const toClone = (outline.value || []).filter((x) => {
        const no = String(x.section_no || '')
        return no === srcTop || no.startsWith(srcTop + '.')
      })
      const payloads = toClone.map((x) => {
        const no = String(x.section_no || '')
        const newNo = no === srcTop ? destTop : destTop + '.' + no.slice(srcTop.length + 1)
        const newName = no === srcTop ? form.section_name : x.section_name
        return {
          section_no: newNo,
          section_name: String(newName || ''),
          level: x.level,
          style: x.style || (x.level === 1 ? 'Heading 1' : x.level === 2 ? 'Heading 2' : 'Heading 3'),
          required: !!x.required,
        }
      })
      payloads.sort((a, b) => a.section_no.split('.').length - b.section_no.split('.').length)
      for (const p of payloads) {
        await api.post(`/template-outline/${tpl.value.template_version_code}/sections`, p)
      }
    } else {
      if (willUpdateStyle) {
        await ElMessageBox.confirm('修改样式将更新该模板下所有相同层级的样式，是否继续？', '提示', { type: 'warning' })
      }
      await api.put(`/template-outline/${tpl.value.template_version_code}/sections/${s!.section_no}`, form)
    }
    await reloadOutline()
    showDialog.value = false
    cloneMode.value = false
    ElMessage.success('已保存')
  } catch (e: any) {
    ElMessage.error(e?.response?.data?.detail || e?.message || '保存失败')
  }
}
</script>

<style scoped>
.page { height: 100%; display: flex; flex-direction: column; }
.header { flex-shrink: 0; display: flex; justify-content: space-between; align-items: center; padding-bottom: 12px; }
.info { display: grid; grid-template-columns: repeat(2, minmax(240px, 1fr)); gap: 8px 16px; }
.row { display: flex; gap: 8px; align-items: center; }
.label { color: #666; }
.content { flex: 1; display: grid; grid-template-columns: minmax(320px, 25%) 1fr; gap: 16px; min-height: 0; }
.sidebar { border: 1px solid #eee; border-radius: 6px; padding: 8px; display: flex; flex-direction: column; min-height: 0; }
.sidebar-tools { display: flex; gap: 6px; margin-bottom: 8px; flex-shrink: 0; }
.sidebar :deep(.el-tree) { flex: 1; min-height: 0; overflow-y: auto; }
.tree-row { display: grid; grid-template-columns: 1fr 28px; align-items: center; gap: 8px; width: 100%; }
.tree-row .el-tooltip { min-width: 0; }
.node-label { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.menu-wrap { width: 32px; display: flex; justify-content: flex-end; }
.more { cursor: pointer; padding: 6px; color: #666; flex-shrink: 0; }
.detail { border: 1px solid #eee; border-radius: 6px; padding: 12px; overflow: auto; min-height: 0; }
.title { font-size: 18px; font-weight: 600; margin-bottom: 12px; }
.kv { margin-bottom: 8px; }
.preview { display: flex; flex-direction: column; gap: 12px; }
.title-row { display: flex; align-items: center; gap: 6px; cursor: pointer; }
.caret { color: #666; }
.section { padding-bottom: 8px; border-bottom: 1px dashed #ddd; }
.section.l2 { padding-left: 18px; }
.section.l3 { padding-left: 36px; }
.h1 { font-size: 20px; font-weight: 700; }
.h2 { font-size: 18px; font-weight: 600; }
.h3 { font-size: 16px; font-weight: 500; }
</style>